home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
prog
/
ixe130.zip
/
IXEBLIT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-09
|
5KB
|
176 lines
/*
Filename : ixeblit.c
Author : Ray E. Bornert II
Date : 1993-APR-09
Copyright (C) 1993 HixoxiH Software. All rights reserved.
*/
//compile line:
// bcc -ml -c -B ixeblit.c
#include "ixeblit.h"
#include <dos.h>
/*
This routine good on 80386's and above for all IXE supported video modes
*/
asm P386
void ixeBlitXY32 //very fast and exclusive
(
unsigned char *dest, //MUST be paragraph aligned for planar mode
void *ixeCode, //address of the precompiled icon
unsigned long DestWidth, //byte width of destination buffer
unsigned long x, //horizontal coordinate based at 0
unsigned long y //vertical coordinate based at 0
)
{
asm {
push ds; //save segment
pushad;
xor edi,edi; //edi=0
lds di,dest; //point ds:di to dest
mov ebx,DestWidth; //load the destination width
mov eax,y; //load the y coordinate
mul ebx; //
add eax,x; //
add edi,eax; //offset += y*DestWidth+x
call dword ptr ixeCode; //goto ixe code
popad;
pop ds; //restore segment
}
}
/*
This routine good on 80286's and above for all IXE supported video modes
where screen size in pixels is less than 65536.
NOTE:
This routine SHOULD NOT be used with video modes
where Pixel ScreenWidth * Pixel ScreenHeight > 65536
Mode 320x200 is okay because 320*200=64000 and is less than 65536
The reason for all of this is that 16bit unsigned math wraps at 65535
For example in mode 320x240 the offset for screen coordinate y=204,x=256
is 320*204+256=65536 but a 16bit unsigned value with all bits on is 65535
If the cpu is allowed to perform 320*204+256 the result will be zero and
320*204+257 will equal 1 and so forth and so on. 16bit math wraps at 65535.
If you are using a video mode with a screen size > 65535 and
you must use 16 bit code then you should use the slower yet reliable
plain jane ixeBlitXY below.
*/
asm P286
void ixeBlitXY16 //fast and restricted
(
unsigned char *dest, //MUST be paragraph aligned for planar mode
void *ixeCode, //address of the precompiled icon
unsigned short DestWidth, //byte width of destination buffer
unsigned short x, //horizontal coordinate based at 0
unsigned short y //vertical coordinate based at 0
)
{
asm {
push ds; //save segment
pusha;
xor di,di; //edi=0
lds di,dest; //point ds:di to dest
mov bx,DestWidth; //load the destination width
mov ax,y; //load the y coordinate
mul bx; //
add ax,x; //
add di,ax; //offset += y*DestWidth+x
call dword ptr ixeCode; //goto ixe code
popa;
pop ds; //restore segment
}
}
/*
This routine good on 80286's and above for all IXE supported video modes
*/
asm P286
void ixeBlitXY //slowest and most generic
(
unsigned char *dest, //MUST be paragraph aligned for planar mode
void *ixeCode, //address of the precompiled icon
unsigned int DestWidth, //byte width of destination buffer
unsigned int x, //horizontal coordinate based at 0
unsigned int y //vertical coordinate based at 0
)
{
//this stuff is slow but we gotta do it to be generic
unsigned short s=FP_SEG(dest);
unsigned short o=FP_OFF(dest);
unsigned long u,adjust;
u=(long)o+((long)y*(long)DestWidth+(long)x);
if (*((unsigned short *)ixeCode) == 0xCF8B)
adjust=64; else
adjust=16;
o = (unsigned short)(u%adjust);
s+= (u/adjust);
dest = (unsigned char *)MK_FP(s,o);
asm {
push ds;
pusha;
lds di,dest;
mov bx,DestWidth;
call dword ptr ixeCode;
popa;
pop ds;
}
}
/*
The code below is desinged to sidestep Interrupt 13 which occurs when the
CPU encounters the following:
mov word ptr [FFFFh], <any 16bit or 32bit operand> or
mov dword ptr [FFFFh], <any 16bit or 32bit operand> or
mov dword ptr [FFFEh], <any 32bit operand> or
mov dword ptr [FFFDh], <any 32bit operand>
*/
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void interrupt ( *oldInt13)(__CPPARGS);
unsigned char far newInt13[256]=
{
0x89,0xDA, //mov dx,bx
0x5B, //pop bx
0x07, //pop es
0x26, //es:
0x80,0x3F,0x66, //cmp byte ptr [bx],66
0x75,0x03, //jne $+5
0x83,0xC3,0x02, //add bx,2
0x83,0xC3,0x06, //add bx,6
0x06, //push es
0x53, //push bx
0x89,0xD3, //mov bx,dx
0xCF //iret
};
/*
This routine saves the current Interrupt Vector for Interrupt 13
and then sets Interrupt Vector 13 to point to newInt13 above.
*/
void disableInt13(void)
{
oldInt13 = getvect(13);
setvect(13,(void interrupt (*)(__CPPARGS)) newInt13);
}
/*
This routine restores the original value of Interrupt Vector 13
*/
void enableInt13(void)
{
setvect(13,oldInt13);
}